﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace Maydew.Windows.Forms.Controls.FlexiCell
{
    /// <summary>
    /// 图形基类。
    /// </summary>
    public class Shape
    {
        #region " 事件 "
        /// <summary>
        /// 单击时发生。
        /// </summary>
        public virtual event EventHandler Click;
        /// <summary>
        /// 双击时发生。
        /// </summary>
        public virtual event EventHandler DoubleClick;
        /// <summary>
        /// 当鼠标按下时发生。
        /// </summary>
        public virtual event System.Windows.Forms.MouseEventHandler MouseDown;
        /// <summary>
        /// 当鼠标弹起时发生。
        /// </summary>
        public virtual event System.Windows.Forms.MouseEventHandler MouseUp;
        /// <summary>
        /// 当鼠标移动时发生。
        /// </summary>
        public virtual event System.Windows.Forms.MouseEventHandler MouseMove;
        /// <summary>
        /// 当鼠标进入时发生。
        /// </summary>
        public virtual event System.Windows.Forms.MouseEventHandler MouseEnter;
        /// <summary>
        /// 当鼠标移出时发生。
        /// </summary>
        public virtual event System.Windows.Forms.MouseEventHandler MouseLeave;
        /// <summary>
        /// 当鼠标单击时发生。
        /// </summary>
        public virtual event System.Windows.Forms.MouseEventHandler MouseClick;
        /// <summary>
        /// 当鼠标双击时发生。
        /// </summary>
        public virtual event System.Windows.Forms.MouseEventHandler MouseDoubleClick;
        /// <summary>
        /// 绘制图形时发生。
        /// </summary>
        public virtual event System.Windows.Forms.PaintEventHandler Paint;
        /// <summary>
        /// Size 属性值改变后发生。
        /// </summary>
        public event EventHandler SizeChanged;
        /// <summary>
        /// Location 属性值改变后发生。
        /// </summary>
        public event EventHandler LocationChanged;
        #endregion

        #region " 私有变量 "
        /// <summary>
        /// 获取或设置宽度。
        /// </summary>
        private int _width;
        /// <summary>
        /// 获取或设置高度。
        /// </summary>
        private int _height;
        /// <summary>
        /// 获取或设置上侧位置。
        /// </summary>
        private int _top;
        /// <summary>
        /// 获取或设置左侧位置。
        /// </summary>
        private int _left;
        /// <summary>
        /// 获取或设置绘图面板。
        /// </summary>
        private System.Windows.Forms.Control _canvas;
        /// <summary>
        /// 获取鼠标进入状态。
        /// </summary>
        private bool _isMouseEnter;
        /// <summary>
        /// 获取或设置是否可见。
        /// </summary>
        private bool _visible;
        /// <summary>
        /// 获取图形边界。
        /// </summary>
        private Rectangle _bounds;
        #endregion

        #region " 构造函数 "
        /// <summary>
        /// 初始化 Shape 类的新实例。
        /// </summary>
        public Shape()
        {
            _visible = true;
        }
        #endregion

        #region " 属性 "
        /// <summary>
        /// 获取或设置左侧位置。
        /// </summary>
        public virtual int Left
        {
            get
            {
                return _left;
            }
            set
            {
                if (_left != value)
                {
                    _left = value;
                    UpdateBounds();
                    OnLocationChanged(EventArgs.Empty);
                }
            }
        }
        /// <summary>
        /// 获取或设置上侧位置。
        /// </summary>
        public virtual int Top
        {
            get
            {
                return _top;
            }
            set
            {
                if (_top != value)
                {
                    _top = value;
                    UpdateBounds();
                    OnLocationChanged(EventArgs.Empty);
                }
            }
        }
        /// <summary>
        /// 获取或设置宽度。
        /// </summary>
        public virtual int Width
        {
            get
            {
                return _width;
            }
            set
            {
                if (_width != value)
                {
                    _width = value;
                    UpdateBounds();
                    OnSizeChanged(EventArgs.Empty);
                }
            }
        }
        /// <summary>
        /// 获取或设置高度。
        /// </summary>
        public virtual int Height
        {
            get
            {
                return _height;
            }
            set
            {
                if (_height != value)
                {
                    _height = value;
                    UpdateBounds();
                    OnSizeChanged(EventArgs.Empty);
                }
            }
        }
        /// <summary>
        /// 获取图形边界。
        /// </summary>
        public virtual System.Drawing.Rectangle Bounds
        {
            get
            {
                return _bounds;
            }
        }
        /// <summary>
        /// 获取或设置是否可见。
        /// </summary>
        public virtual bool Visible
        {
            get { return _visible; }
            set
            {
                if (_visible != value)
                {
                    _visible = value;
                }
            }
        }
        /// <summary>
        /// 获取或设置绘图面板。
        /// </summary>
        protected internal virtual System.Windows.Forms.Control Canvas
        {
            get
            {
                return _canvas;
            }
            set
            {
                if (_canvas != value)
                {
                    if (_canvas != null)
                    {
                        _canvas.Click -= new EventHandler(_canvas_Click);
                        _canvas.DoubleClick -= new EventHandler(_canvas_DoubleClick);
                        _canvas.MouseClick -= new System.Windows.Forms.MouseEventHandler(_canvas_MouseClick);
                        _canvas.MouseDoubleClick -= new System.Windows.Forms.MouseEventHandler(_canvas_MouseDoubleClick);
                        _canvas.MouseDown -= new System.Windows.Forms.MouseEventHandler(_canvas_MouseDown);
                        _canvas.MouseMove -= new System.Windows.Forms.MouseEventHandler(_canvas_MouseMove);
                        _canvas.MouseUp -= new System.Windows.Forms.MouseEventHandler(_canvas_MouseUp);
                    }
                    _canvas = value;
                    if (_canvas != null)
                    {
                        _canvas.Click += new EventHandler(_canvas_Click);
                        _canvas.DoubleClick += new EventHandler(_canvas_DoubleClick);
                        _canvas.MouseClick += new System.Windows.Forms.MouseEventHandler(_canvas_MouseClick);
                        _canvas.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(_canvas_MouseDoubleClick);
                        _canvas.MouseDown += new System.Windows.Forms.MouseEventHandler(_canvas_MouseDown);
                        _canvas.MouseMove += new System.Windows.Forms.MouseEventHandler(_canvas_MouseMove);
                        _canvas.MouseUp += new System.Windows.Forms.MouseEventHandler(_canvas_MouseUp);
                    }
                }
            }
        }
        #endregion

        #region " Canvas 事件处理 "
        /// <summary>
        /// 当 Canvas 单击时发生。
        /// </summary>
        /// <param name="sender">事件对象。</param>
        /// <param name="e">事件参数。</param>
        private void _canvas_Click(object sender, EventArgs e)
        {
            OnClick(e);
        }
        /// <summary>
        /// 当 Canvas 双击时发生。
        /// </summary>
        /// <param name="sender">事件对象。</param>
        /// <param name="e">事件参数。</param>
        private void _canvas_DoubleClick(object sender, EventArgs e)
        {
            OnDoubleClick(e);
        }
        /// <summary>
        /// 当 Canvas 鼠标单击时发生。
        /// </summary>
        /// <param name="sender">事件对象。</param>
        /// <param name="e">事件参数。</param>
        private void _canvas_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            OnMouseClick(e);
        }
        /// <summary>
        /// 当 Canvas 鼠标双击时发生。
        /// </summary>
        /// <param name="sender">事件对象。</param>
        /// <param name="e">事件参数。</param>
        private void _canvas_MouseDoubleClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            OnMouseDoubleClick(e);
        }
        /// <summary>
        /// 当 Canvas 鼠标按下时发生。
        /// </summary>
        /// <param name="sender">事件对象。</param>
        /// <param name="e">事件参数。</param>
        private void _canvas_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            OnMouseDown(e);
        }
        /// <summary>
        /// 当 Canvas 鼠标移动时发生。
        /// </summary>
        /// <param name="sender">事件对象。</param>
        /// <param name="e">事件参数。</param>
        private void _canvas_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (Contains(e.Location))
            {
                if (!_isMouseEnter)
                {
                    _isMouseEnter = true;
                    OnMouseEnter(e);
                }

                OnMouseMove(e);
            }
            else if (_isMouseEnter)
            {
                _isMouseEnter = false;
                OnMouseLeave(e);
            }
        }
        /// <summary>
        /// 当 Canvas 鼠标弹起时发生。
        /// </summary>
        /// <param name="sender">事件对象。</param>
        /// <param name="e">事件参数。</param>
        private void _canvas_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            OnMouseUp(e);
        }
        #endregion

        #region " 方法 "
        /// <summary>
        /// 获取 pt 是否包含在图形中。
        /// </summary>
        /// <param name="pt">要验证的 Point。</param>
        /// <returns>成功，返回 true，否则，返回 false。</returns>
        public virtual bool Contains(System.Drawing.Point pt)
        {
            return Bounds.Contains(pt);
        }
        /// <summary>
        /// 获取 rect 是否包含在图形中。
        /// </summary>
        /// <param name="rect">要验证的 Rectangle。</param>
        /// <returns>成功，返回 true，否则，返回 false。</returns>
        public virtual bool Contains(System.Drawing.Rectangle rect)
        {
            return Bounds.Contains(rect);
        }
        /// <summary>
        /// 获取 rect 是否与图形相交。
        /// </summary>
        /// <param name="rect">要验证的 Rectangle。</param>
        /// <returns>成功，返回 true，否则，返回 false。</returns>
        public virtual bool IntersectsWith(System.Drawing.Rectangle rect)
        {
            return Bounds.IntersectsWith(rect);
        }
        #endregion

        #region " 绘制方法 "
        /// <summary>
        /// 绘制图形。
        /// </summary>
        /// <param name="e">绘图参数。</param>
        public virtual void Painting(System.Windows.Forms.PaintEventArgs e)
        {
            if (_visible)
            {
                OnPaint(e);
            }
        }
        #endregion

        #region " 友元方法--事件触发 "
        /// <summary>
        /// 触发 Click 事件。
        /// </summary>
        /// <param name="e">事件参数。</param>
        protected virtual void OnClick(EventArgs e)
        {
            if (_visible && Contains(System.Windows.Forms.Cursor.Position))
            {
                if (Click != null) Click(this, e);
            }
        }
        /// <summary>
        /// 触发 DoubleClick 事件。
        /// </summary>
        /// <param name="e">事件参数。</param>
        protected virtual void OnDoubleClick(EventArgs e)
        {
            if (_visible && Contains(System.Windows.Forms.Cursor.Position))
            {
                if (DoubleClick != null) DoubleClick(this, e);
            }
        }
        /// <summary>
        /// 触发 MouseClick 事件。
        /// </summary>
        /// <param name="e">事件参数。</param>
        protected virtual void OnMouseClick(System.Windows.Forms.MouseEventArgs e)
        {
            if (_visible && Contains(e.Location))
            {
                if (MouseClick != null) MouseClick(this, e);
            }
        }
        /// <summary>
        /// 触发 MouseDoubleClick 事件。
        /// </summary>
        /// <param name="e">事件参数。</param>
        protected virtual void OnMouseDoubleClick(System.Windows.Forms.MouseEventArgs e)
        {
            if (_visible && Contains(e.Location))
            {
                if (MouseDoubleClick != null) MouseDoubleClick(this, e);
            }
        }
        /// <summary>
        /// 触发 MouseDown 事件。
        /// </summary>
        /// <param name="e">事件参数。</param>
        protected virtual void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
        {
            if (_visible && Contains(e.Location))
            {
                if (MouseDown != null) MouseDown(this, e);
            }
        }
        /// <summary>
        /// 触发 MouseEnter 事件。
        /// </summary>
        /// <param name="e">事件参数。</param>
        protected virtual void OnMouseEnter(System.Windows.Forms.MouseEventArgs e)
        {
            if (_visible && Contains(e.Location))
            {
                if (MouseEnter != null) MouseEnter(this, e);
            }
        }
        /// <summary>
        /// 触发 MouseLeave 事件。
        /// </summary>
        /// <param name="e">事件参数。</param>
        protected virtual void OnMouseLeave(System.Windows.Forms.MouseEventArgs e)
        {
            if (_visible && Contains(e.Location))
            {
                if (MouseLeave != null) MouseLeave(this, e);
            }
        }
        /// <summary>
        /// 触发 MouseMove 事件。
        /// </summary>
        /// <param name="e">事件参数。</param>
        protected virtual void OnMouseMove(System.Windows.Forms.MouseEventArgs e)
        {
            if (_visible && Contains(e.Location))
            {
                if (MouseMove != null) MouseMove(this, e);
            }
        }
        /// <summary>
        /// 触发 MouseUp 事件。
        /// </summary>
        /// <param name="e">事件参数。</param>
        protected virtual void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
        {
            if (_visible && Contains(e.Location))
            {
                if (MouseUp != null) MouseUp(this, e);
            }
        }
        /// <summary>
        /// 触发 Paint 事件。
        /// </summary>
        /// <param name="e">事件参数。</param>
        protected virtual void OnPaint(System.Windows.Forms.PaintEventArgs e)
        {
            if (Paint != null) Paint(this, e);
        }
        /// <summary>
        /// 触发 SizeChanged 事件。
        /// </summary>
        /// <param name="e">事件参数。</param>
        protected virtual void OnSizeChanged(EventArgs e)
        {
            if (SizeChanged != null) SizeChanged(this, e);
        }
        /// <summary>
        /// 触发 LocationChanged 事件。
        /// </summary>
        /// <param name="e">事件参数。</param>
        protected virtual void OnLocationChanged(EventArgs e)
        {
            if (LocationChanged != null) LocationChanged(this, e);
        }
        #endregion

        #region " 友元方法 "
        /// <summary>
        /// 更新 Bounds 属性值。
        /// </summary>
        protected virtual void UpdateBounds()
        {
            _bounds = new Rectangle(_left, _top, _width, _height);
        }
        #endregion

        #region " 静态方法 "
        /// <summary>
        /// 将 ContentAlignment 类型转换成 StringFormat 类型。
        /// </summary>
        /// <param name="sf">StringFormat 类型对象。</param>
        /// <param name="align">ContentAlignment 类型对象。</param>
        internal static void ConvertContentAlignment(StringFormat sf, ContentAlignment align)
        {
            switch (align)
            {
                case ContentAlignment.BottomCenter:
                    sf.Alignment = StringAlignment.Center;
                    sf.LineAlignment = StringAlignment.Far;
                    break;
                case ContentAlignment.BottomLeft:
                    sf.Alignment = StringAlignment.Near;
                    sf.LineAlignment = StringAlignment.Far;
                    break;
                case ContentAlignment.BottomRight:
                    sf.Alignment = StringAlignment.Far;
                    sf.LineAlignment = StringAlignment.Far;
                    break;
                case ContentAlignment.MiddleCenter:
                    sf.Alignment = StringAlignment.Center;
                    sf.LineAlignment = StringAlignment.Center;
                    break;
                case ContentAlignment.MiddleLeft:
                    sf.Alignment = StringAlignment.Near;
                    sf.LineAlignment = StringAlignment.Center;
                    break;
                case ContentAlignment.MiddleRight:
                    sf.Alignment = StringAlignment.Far;
                    sf.LineAlignment = StringAlignment.Center;
                    break;
                case ContentAlignment.TopCenter:
                    sf.Alignment = StringAlignment.Center;
                    sf.LineAlignment = StringAlignment.Near;
                    break;
                case ContentAlignment.TopLeft:
                    sf.Alignment = StringAlignment.Near;
                    sf.LineAlignment = StringAlignment.Near;
                    break;
                case ContentAlignment.TopRight:
                    sf.Alignment = StringAlignment.Far;
                    sf.LineAlignment = StringAlignment.Near;
                    break;
            }
        }
        #endregion
    }
}
